#ifndef __SLOT_TYPES_HEADER
#define __SLOT_TYPES_HEADER

#include <stdexcept>
#include <string>

const int MIN_DEFINED_FILL_TYPE 	= 0;
const int ARMOR_FILL_TYPE			= 0;

const int SHORT_FILL_TYPE 			= 1; 
const int MEDIUM_FILL_TYPE 			= 2;

const int LONG_FILL_TYPE 			= 3;
const int MAX_DEFINED_FILL_TYPE 	= 3;

inline const int LOADABLE( bool LOAD ) {
	return LOAD ? 5 : 0;
}

inline std::string STRING_AC( bool LOAD ) {
	return (LOAD ? "Loadable" : "Armor Only");	
}

inline const int FILL_COST( int FILL_TYPE ) {
	if ( FILL_TYPE < MIN_DEFINED_FILL_TYPE ||
		 FILL_TYPE > MAX_DEFINED_FILL_TYPE )
			throw std::invalid_argument("FILL_COST(int)");
	
	switch(FILL_TYPE) {
		case ARMOR_FILL_TYPE:
			return 5;
		case SHORT_FILL_TYPE:
			return 10;
		case MEDIUM_FILL_TYPE:
			return 20;
		case LONG_FILL_TYPE:
			return 25;
		default:;
	}
	throw std::runtime_error("FILL_CONST(int)");
}

inline std::string STRING_FILL(int FILL) {	
	std::string value;
	switch ( FILL ) {
		case 0:
			value = "Armor";
			break;
		case 1:
			value = "Short Cannon";
			break;
		case 2:
			value = "Medium Cannon";
			break;
		case 3:
			value = "Long Cannon";
			break;
		default:
			value = "Unknown Fill";
	}
	return value;
}


const int MIN_DEFINED_SLOT_TYPE 	= 0;
const int ARMOR_SLOT_TYPE 			= 0;

const int LEFT_SLOT_TYPE 			= 1;
const int MIDDLE_SLOT_TYPE 			= 2;
const int RIGHT_SLOT_TYPE 			= 4;
const int LEFT_MIDDLE_SLOT_TYPE 	= 3;
const int RIGHT_MIDDLE_SLOT_TYPE 	= 6;
const int LEFT_RIGHT_SLOT_TYPE 		= 5;

const int OMNI_SLOT_TYPE 			= 7;
const int MAX_DEFINED_SLOT_TYPE		= 7;

inline const int SLOT_COST ( int SLOT_TYPE ) {
	if ( SLOT_TYPE < MIN_DEFINED_SLOT_TYPE ||
		 SLOT_TYPE > MAX_DEFINED_SLOT_TYPE )
			throw std::invalid_argument("SLOT_COST(int)");

	switch ( SLOT_TYPE ) {
		case ARMOR_SLOT_TYPE:
			return 10;
		case LEFT_SLOT_TYPE:
			return 20;
		case MIDDLE_SLOT_TYPE:
			return 20;
		case RIGHT_SLOT_TYPE:
			return 20;
		case LEFT_MIDDLE_SLOT_TYPE:
			return 30;
		case RIGHT_MIDDLE_SLOT_TYPE:
			return 30;
		case LEFT_RIGHT_SLOT_TYPE:
			return 25;
		case OMNI_SLOT_TYPE:
			return 45;
		default:;
	}

	throw std::runtime_error("SLOT_COST(int)");
}

struct Directions {
	bool left;
	bool middle;
	bool right;
};

const Directions ARMOR_SLOT 		= { 0, 0, 0 };
const Directions LEFT_SLOT			= { 1, 0, 0 };
const Directions MIDDLE_SLOT		= { 0, 1, 0 };
const Directions RIGHT_SLOT			= { 0, 0, 1 };
const Directions LEFT_MIDDLE_SLOT 	= { 1, 1, 0 };
const Directions RIGHT_MIDDLE_SLOT	= { 0, 1, 1 };
const Directions LEFT_RIGHT_SLOT	= { 1, 0, 1 };
const Directions OMNI_SLOT			= { 1, 1, 1 };

inline int SLOT_TYPE( Directions DIRS ) {
	return DIRS.left + 2*DIRS.middle + 4*DIRS.right;
}

inline Directions REV_SLOT_TYPE( int DIRS ) {
	Directions dir;
	dir.left = DIRS % 2;
	DIRS = DIRS >> 1;
	dir.middle = DIRS % 2;
	DIRS = DIRS >> 1;
	dir.right = DIRS % 2;

	return dir;
}

inline std::string STRING_DIRS( Directions DIRS ) {
	return "["+std::to_string(DIRS.left)
				+","+std::to_string(DIRS.middle)
				+","+std::to_string(DIRS.right)+"]";
}

inline int HP_SLOT_COST( int _hp ) {
	if ( _hp < 1 ) throw std::invalid_argument("HP_SLOT_COST(int)");

	return 10*_hp;
}
























#endif
